(globalThis.TURBOPACK = globalThis.TURBOPACK || []).push([typeof document === "object" ? document.currentScript : undefined, { "[turbopack]/browser/dev/hmr-client/hmr-client.ts [app-client] (ecmascript)": ((__turbopack_context__) => { "use strict"; var { g: global, __dirname } = __turbopack_context__; { /// /// /// /// __turbopack_context__.s({ "connect": (()=>connect), "setHooks": (()=>setHooks), "subscribeToUpdate": (()=>subscribeToUpdate) }); function connect({ addMessageListener, sendMessage, onUpdateError = console.error }) { addMessageListener((msg)=>{ switch(msg.type){ case "turbopack-connected": handleSocketConnected(sendMessage); break; default: try { if (Array.isArray(msg.data)) { for(let i = 0; i < msg.data.length; i++){ handleSocketMessage(msg.data[i]); } } else { handleSocketMessage(msg.data); } applyAggregatedUpdates(); } catch (e) { console.warn("[Fast Refresh] performing full reload\n\n" + "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" + "You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n" + "Consider migrating the non-React component export to a separate file and importing it into both files.\n\n" + "It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n" + "Fast Refresh requires at least one parent function component in your React tree."); onUpdateError(e); location.reload(); } break; } }); const queued = globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS; if (queued != null && !Array.isArray(queued)) { throw new Error("A separate HMR handler was already registered"); } globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = { push: ([chunkPath, callback])=>{ subscribeToChunkUpdate(chunkPath, sendMessage, callback); } }; if (Array.isArray(queued)) { for (const [chunkPath, callback] of queued){ subscribeToChunkUpdate(chunkPath, sendMessage, callback); } } } const updateCallbackSets = new Map(); function sendJSON(sendMessage, message) { sendMessage(JSON.stringify(message)); } function resourceKey(resource) { return JSON.stringify({ path: resource.path, headers: resource.headers || null }); } function subscribeToUpdates(sendMessage, resource) { sendJSON(sendMessage, { type: "turbopack-subscribe", ...resource }); return ()=>{ sendJSON(sendMessage, { type: "turbopack-unsubscribe", ...resource }); }; } function handleSocketConnected(sendMessage) { for (const key of updateCallbackSets.keys()){ subscribeToUpdates(sendMessage, JSON.parse(key)); } } // we aggregate all pending updates until the issues are resolved const chunkListsWithPendingUpdates = new Map(); function aggregateUpdates(msg) { const key = resourceKey(msg.resource); let aggregated = chunkListsWithPendingUpdates.get(key); if (aggregated) { aggregated.instruction = mergeChunkListUpdates(aggregated.instruction, msg.instruction); } else { chunkListsWithPendingUpdates.set(key, msg); } } function applyAggregatedUpdates() { if (chunkListsWithPendingUpdates.size === 0) return; hooks.beforeRefresh(); for (const msg of chunkListsWithPendingUpdates.values()){ triggerUpdate(msg); } chunkListsWithPendingUpdates.clear(); finalizeUpdate(); } function mergeChunkListUpdates(updateA, updateB) { let chunks; if (updateA.chunks != null) { if (updateB.chunks == null) { chunks = updateA.chunks; } else { chunks = mergeChunkListChunks(updateA.chunks, updateB.chunks); } } else if (updateB.chunks != null) { chunks = updateB.chunks; } let merged; if (updateA.merged != null) { if (updateB.merged == null) { merged = updateA.merged; } else { // Since `merged` is an array of updates, we need to merge them all into // one, consistent update. // Since there can only be `EcmascriptMergeUpdates` in the array, there is // no need to key on the `type` field. let update = updateA.merged[0]; for(let i = 1; i < updateA.merged.length; i++){ update = mergeChunkListEcmascriptMergedUpdates(update, updateA.merged[i]); } for(let i = 0; i < updateB.merged.length; i++){ update = mergeChunkListEcmascriptMergedUpdates(update, updateB.merged[i]); } merged = [ update ]; } } else if (updateB.merged != null) { merged = updateB.merged; } return { type: "ChunkListUpdate", chunks, merged }; } function mergeChunkListChunks(chunksA, chunksB) { const chunks = {}; for (const [chunkPath, chunkUpdateA] of Object.entries(chunksA)){ const chunkUpdateB = chunksB[chunkPath]; if (chunkUpdateB != null) { const mergedUpdate = mergeChunkUpdates(chunkUpdateA, chunkUpdateB); if (mergedUpdate != null) { chunks[chunkPath] = mergedUpdate; } } else { chunks[chunkPath] = chunkUpdateA; } } for (const [chunkPath, chunkUpdateB] of Object.entries(chunksB)){ if (chunks[chunkPath] == null) { chunks[chunkPath] = chunkUpdateB; } } return chunks; } function mergeChunkUpdates(updateA, updateB) { if (updateA.type === "added" && updateB.type === "deleted" || updateA.type === "deleted" && updateB.type === "added") { return undefined; } if (updateA.type === "partial") { invariant(updateA.instruction, "Partial updates are unsupported"); } if (updateB.type === "partial") { invariant(updateB.instruction, "Partial updates are unsupported"); } return undefined; } function mergeChunkListEcmascriptMergedUpdates(mergedA, mergedB) { const entries = mergeEcmascriptChunkEntries(mergedA.entries, mergedB.entries); const chunks = mergeEcmascriptChunksUpdates(mergedA.chunks, mergedB.chunks); return { type: "EcmascriptMergedUpdate", entries, chunks }; } function mergeEcmascriptChunkEntries(entriesA, entriesB) { return { ...entriesA, ...entriesB }; } function mergeEcmascriptChunksUpdates(chunksA, chunksB) { if (chunksA == null) { return chunksB; } if (chunksB == null) { return chunksA; } const chunks = {}; for (const [chunkPath, chunkUpdateA] of Object.entries(chunksA)){ const chunkUpdateB = chunksB[chunkPath]; if (chunkUpdateB != null) { const mergedUpdate = mergeEcmascriptChunkUpdates(chunkUpdateA, chunkUpdateB); if (mergedUpdate != null) { chunks[chunkPath] = mergedUpdate; } } else { chunks[chunkPath] = chunkUpdateA; } } for (const [chunkPath, chunkUpdateB] of Object.entries(chunksB)){ if (chunks[chunkPath] == null) { chunks[chunkPath] = chunkUpdateB; } } if (Object.keys(chunks).length === 0) { return undefined; } return chunks; } function mergeEcmascriptChunkUpdates(updateA, updateB) { if (updateA.type === "added" && updateB.type === "deleted") { // These two completely cancel each other out. return undefined; } if (updateA.type === "deleted" && updateB.type === "added") { const added = []; const deleted = []; const deletedModules = new Set(updateA.modules ?? []); const addedModules = new Set(updateB.modules ?? []); for (const moduleId of addedModules){ if (!deletedModules.has(moduleId)) { added.push(moduleId); } } for (const moduleId of deletedModules){ if (!addedModules.has(moduleId)) { deleted.push(moduleId); } } if (added.length === 0 && deleted.length === 0) { return undefined; } return { type: "partial", added, deleted }; } if (updateA.type === "partial" && updateB.type === "partial") { const added = new Set([ ...updateA.added ?? [], ...updateB.added ?? [] ]); const deleted = new Set([ ...updateA.deleted ?? [], ...updateB.deleted ?? [] ]); if (updateB.added != null) { for (const moduleId of updateB.added){ deleted.delete(moduleId); } } if (updateB.deleted != null) { for (const moduleId of updateB.deleted){ added.delete(moduleId); } } return { type: "partial", added: [ ...added ], deleted: [ ...deleted ] }; } if (updateA.type === "added" && updateB.type === "partial") { const modules = new Set([ ...updateA.modules ?? [], ...updateB.added ?? [] ]); for (const moduleId of updateB.deleted ?? []){ modules.delete(moduleId); } return { type: "added", modules: [ ...modules ] }; } if (updateA.type === "partial" && updateB.type === "deleted") { // We could eagerly return `updateB` here, but this would potentially be // incorrect if `updateA` has added modules. const modules = new Set(updateB.modules ?? []); if (updateA.added != null) { for (const moduleId of updateA.added){ modules.delete(moduleId); } } return { type: "deleted", modules: [ ...modules ] }; } // Any other update combination is invalid. return undefined; } function invariant(_, message) { throw new Error(`Invariant: ${message}`); } const CRITICAL = [ "bug", "error", "fatal" ]; function compareByList(list, a, b) { const aI = list.indexOf(a) + 1 || list.length; const bI = list.indexOf(b) + 1 || list.length; return aI - bI; } const chunksWithIssues = new Map(); function emitIssues() { const issues = []; const deduplicationSet = new Set(); for (const [_, chunkIssues] of chunksWithIssues){ for (const chunkIssue of chunkIssues){ if (deduplicationSet.has(chunkIssue.formatted)) continue; issues.push(chunkIssue); deduplicationSet.add(chunkIssue.formatted); } } sortIssues(issues); hooks.issues(issues); } function handleIssues(msg) { const key = resourceKey(msg.resource); let hasCriticalIssues = false; for (const issue of msg.issues){ if (CRITICAL.includes(issue.severity)) { hasCriticalIssues = true; } } if (msg.issues.length > 0) { chunksWithIssues.set(key, msg.issues); } else if (chunksWithIssues.has(key)) { chunksWithIssues.delete(key); } emitIssues(); return hasCriticalIssues; } const SEVERITY_ORDER = [ "bug", "fatal", "error", "warning", "info", "log" ]; const CATEGORY_ORDER = [ "parse", "resolve", "code generation", "rendering", "typescript", "other" ]; function sortIssues(issues) { issues.sort((a, b)=>{ const first = compareByList(SEVERITY_ORDER, a.severity, b.severity); if (first !== 0) return first; return compareByList(CATEGORY_ORDER, a.category, b.category); }); } const hooks = { beforeRefresh: ()=>{}, refresh: ()=>{}, buildOk: ()=>{}, issues: (_issues)=>{} }; function setHooks(newHooks) { Object.assign(hooks, newHooks); } function handleSocketMessage(msg) { sortIssues(msg.issues); handleIssues(msg); switch(msg.type){ case "issues": break; case "partial": // aggregate updates aggregateUpdates(msg); break; default: // run single update const runHooks = chunkListsWithPendingUpdates.size === 0; if (runHooks) hooks.beforeRefresh(); triggerUpdate(msg); if (runHooks) finalizeUpdate(); break; } } function finalizeUpdate() { hooks.refresh(); hooks.buildOk(); // This is used by the Next.js integration test suite to notify it when HMR // updates have been completed. // TODO: Only run this in test environments (gate by `process.env.__NEXT_TEST_MODE`) if (globalThis.__NEXT_HMR_CB) { globalThis.__NEXT_HMR_CB(); globalThis.__NEXT_HMR_CB = null; } } function subscribeToChunkUpdate(chunkListPath, sendMessage, callback) { return subscribeToUpdate({ path: chunkListPath }, sendMessage, callback); } function subscribeToUpdate(resource, sendMessage, callback) { const key = resourceKey(resource); let callbackSet; const existingCallbackSet = updateCallbackSets.get(key); if (!existingCallbackSet) { callbackSet = { callbacks: new Set([ callback ]), unsubscribe: subscribeToUpdates(sendMessage, resource) }; updateCallbackSets.set(key, callbackSet); } else { existingCallbackSet.callbacks.add(callback); callbackSet = existingCallbackSet; } return ()=>{ callbackSet.callbacks.delete(callback); if (callbackSet.callbacks.size === 0) { callbackSet.unsubscribe(); updateCallbackSets.delete(key); } }; } function triggerUpdate(msg) { const key = resourceKey(msg.resource); const callbackSet = updateCallbackSets.get(key); if (!callbackSet) { return; } for (const callback of callbackSet.callbacks){ callback(msg); } if (msg.type === "notFound") { // This indicates that the resource which we subscribed to either does not exist or // has been deleted. In either case, we should clear all update callbacks, so if a // new subscription is created for the same resource, it will send a new "subscribe" // message to the server. // No need to send an "unsubscribe" message to the server, it will have already // dropped the update stream before sending the "notFound" message. updateCallbackSets.delete(key); } } }}), }]); //# sourceMappingURL=%5Bturbopack%5D_browser_dev_hmr-client_hmr-client_ts_61dcf9ba._.js.map